home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 9 / FM Towns Free Software Collection 9.iso / t_os / game / fall / ball.c next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  42.0 KB  |  1,415 lines

  1. /* ボール 1994年5月22日 - 6月5日 */
  2. /*
  3.    1994年5月25日 ボールの移動処理完成
  4.    1994年5月26日 チェックポイント処理追加
  5.    1994年5月27日 ボールのバウンド音追加
  6.    1994年5月29日 デモ,選択,トップタイム画面追加
  7.    1994年5月30日 ファイルリードライト追加
  8.    1994年5月31日 キャラクタが鏡像になるバグ修正
  9.    1994年6月04日 マップデータ完成(α版完成)
  10.    1994年6月05日 初期仮想VRAM作成の高速化
  11. */
  12.  
  13. /* ボール1 10箇所のチェックポイントの通過時間を競う
  14.    ボール2 ゴールにたどり着くまでの時間を競う */
  15.  
  16. #include <math.h>
  17. #include <stdio.h>
  18.  
  19.  
  20. #define R 32   /* 赤 */
  21. #define G 1024 /* 緑 */
  22. #define B 1    /* 青 */
  23.  
  24. #define PANEL ((R+G+B)*15) /* 背景色 */
  25.  
  26. #define MAX_X 896   /* 仮想VRAMのX方向の大きさ(dot単位) */
  27. #define MAX_Y 896   /* 仮想VRAMのY方向の大きさ(dot単位) */
  28.  
  29. #define DSP_X 112   /* 表示画面のX方向の大きさ(dot単位) */
  30. #define DSP_Y 112   /* 表示画面のY方向の大きさ(dot単位) */
  31.  
  32. #define DX (-56)    /* 表示画面左上のX座標 */
  33. #define DY (-56)    /* 表示画面左上のY座標 */
  34.  
  35. #define POINT 0x1000 /* 固定少数化の倍率 */
  36. #define SHIFT 12     /* 固定少数化の倍率(2の乗数) */
  37.  
  38. #define WALL 31      /* 壁のMAPコードの最大値 */
  39.  
  40. #define LEVEL 50     /* ゲームモード0の時の障害物の数 */
  41.  
  42.  
  43. char CHRFILE[]="chr.pat";    /* キャラクタパターンファイル名 */
  44. char TILEFILE[]="tile.pat";  /* タイルパターンファイル名 */
  45. char BESTFILE[]="best.tim";  /* ベストタイムファイル名 */
  46. char MAPFILE[]="map.dat";    /* マップデータのファイル名 */
  47. char GOALFILE[]="point.pat"; /* ゴールパターンのファイル名 */
  48.  
  49.  
  50. char gwork[1540];
  51.  
  52. double RAD=3.141592/180; /* ラジアン */
  53. short kvram[MAX_X][MAX_Y];
  54. unsigned int W_PAGE; /* レイア1の書き込みページ(0=(0,0) 0x20000=(0,128)) */
  55. unsigned int VRAM;   /* VRAMの先頭アドレス */
  56. unsigned int MYADD;  /* ボールの画面上での描画アドレス */
  57.  
  58. int X=MAX_X/2;     /* 仮想VRAMの中心(X座標) */
  59. int Y=MAX_Y/2;     /* 仮想VRAMの中心(Y座標) */
  60.  
  61. /* 三角関数テーブル */
  62. int COS[72];  /* 余弦×POINT    (360°を72分割) */
  63. int SIN[72];  /* 正弦×(-POINT) (360°を72分割) */
  64.  
  65. /* roll3用オフセットテーブル */
  66. int XOF[72][DSP_X],YOF[72][DSP_Y];
  67.  
  68. int MAP[56][56];  /* マップ */
  69.                   /* マップコード 0      - 9    : チェックポイント
  70.                                   10     - WALL : 障害物
  71.                                   WALL+1        : チェックポイントの脱け殻
  72.                                   WALL+2 -      : 空間 */
  73. /* この配置なら、障害物とチェックポイントの判定は MAP<=WALLの1回で済む。
  74.    モード0の時はチェックポイントの通過判定は MAP==NEXT で行い、
  75.    NEXT==10 でゴール。(NEXTの初期値は0)
  76.    すでに通過済のチェックポイントは通過可能にするために、
  77.    WALL+1(チェックポイントの脱け殻)に変えている。
  78.    モード1の時は、NEXTを予め9にしておき、チェックポイントの通過判定は
  79.    MAP<=NEXT で行う。
  80.    こうする事で、どのチェックポイントを通過しても、NEXT==10 となるので、
  81.    1回のチェックポイント通過でゴールとなるうえ、ゴール用キャラクタパターンを
  82.    10種類使用できる。 */
  83.  
  84. int CORSE[5][56][56]; /* サーキットのマップデータ */
  85.  
  86. short tile[64][256]; /* 背景のキャラクタパターン
  87.                           0      - 9    : チェックポイント(ゴール)
  88.                           10     - WALL : 障害物
  89.                           WALL+1        : チェックポイントの脱け殻
  90.                           WALL+2 -      : 空間 */
  91.  
  92. short chr[13][256];  /* 背景以外のキャラクタパターン
  93.                           0 - 9 : 数字
  94.                           10    : ボール0
  95.                           11    : ボール1
  96.                           12    : ボール2 */
  97.  
  98. short goal_chr[20][256]; /* ゴールのキャラクタパターン
  99.                              0  - 9 : チェックポイント
  100.                             10 - 19 : ゴール */
  101.  
  102.  
  103. /* ボール変数 */
  104. int bx,by;   /* 表示画面の回転中心に対応する仮想VRAMの座標 */
  105. int ax,ay;   /* 加速度 */
  106. int vx,vy;   /* 速度 */
  107. int deg;     /* 重力の方向(0 <-> 71) */
  108. int VX_MIN,VX_MAX,VY_MIN,VY_MAX; /* 最高速,最低速 */
  109. int BALL;    /* ボールの種類 0:軽い 1:普通 2:重い */
  110. int A;       /* 重力加速度(1/A) */
  111. int V;       /* 最高速の絶対値 */
  112. int BOUND;   /* 跳ね返り係数(%) */
  113.  
  114.  
  115. /* ビュー変数 */
  116. int v_next_x[10],v_next_y[10]; /* 次に通るべきチェックポイントの座標 */
  117. int v_flush; /* 次に通るべきチェックポイントの点滅フラグ */
  118. int MX,MY; /* ビューの表示位置 */
  119.  
  120. int GAME=0;  /* ゲーム終了フラグ 0 : ゲーム続行  1 : ゲーム終了 */
  121.  
  122. int TIME;     /* スタートしてからの経過時間 */
  123. int TIME_UP;  /* 時間切れフラグ 0 : 時間内  1 : 時間切れ */
  124. int BEST_TIME[6][3][8]; /* ゲームモード,ボール別の最高タイム(8位) */ 
  125.  
  126. int MODE; /* ゲームモード  0 : 10箇所のチェックポイントの通過時間を競う
  127.                        1 - 5 : ゴールにたどり着くまでの時間を競う(コースNo) */
  128.  
  129. int END;  /* ステージ終了フラグ 0 : ステージ続行  1 : ステージ終了 */
  130.  
  131. int NEXT; /* 次に通過するチェックポイントの番号
  132.              ゲームモード  0 : 0 - 9  ゲームモード  1 : 9 */
  133.  
  134.  
  135.  
  136. /* サウンド変数 */
  137. int spoint[6];                     /* サウンドデータポインタ */
  138. int sinit[28];                     /* サウンドデータ先頭ポインタ */
  139. int skunt[6];                      /* カウンタ */
  140. int feed[6]={1,6,2,2,4,7};         /* 各チャンネルの音質 */
  141.  
  142. int BF;  /* バウンドフラグ(転がりの際、バウンド音が連続するのを防止するフラグ)
  143.               壁に接触した際の速度反転によって、反対方向に1dot以上動いたか
  144.               1:動いた 0:動かない(1の場合転がりなのでバウンド音は出さない) */
  145.  
  146.  
  147.  
  148. main()
  149.  
  150. {
  151.  int i,j,k,s,rc;
  152.  
  153.  
  154.  load_best(); /* ベストタイムのバイナリ形式load */
  155.  if (load_chr()==0) return 0;  /* キャラクタパターンデータのバイナリ形式load */
  156.  if (load_tile()==0) return 0; /* タイルパターンデータのバイナリ形式load */
  157.  if (load_map()==0) return 0;  /* マップデータのバイナリ形式load */
  158.  if (load_goal()==0) return 0; /* ゴールパターンデータのバイナリ形式load */
  159.  
  160.  
  161.  init_tri();  /* 三角関数テーブルの作成 */
  162.  init_tri3(); /* roll3用オフセットテーブルの作成 */
  163.  
  164.  EGB_init( gwork, 1536 ) ;               /* BIOSの初期化 */
  165.  EGB_resolution( gwork, 0, 10 ) ;        /* ページ0の解像度設定(モード10) */
  166.  EGB_resolution( gwork, 1, 10 ) ;        /* ページ1の解像度設定(モード10) */
  167.  EGB_displayPage( gwork, 1, 3 ) ;        /* 表示ページの設定(両ページ) */
  168.  
  169.  EGB_writePage( gwork, 1 ) ;             /* 書き込みページを1に */
  170.  EGB_displayStart( gwork, 2, 4, 4 ) ;    /* 表示範囲の倍率設定(4X4) */
  171.  EGB_displayStart( gwork, 3, 128,240 ) ; /* 表示範囲の設定 */
  172.  EGB_displayStart( gwork, 3, 160,240 ) ; /* 表示範囲の設定 */
  173.  EGB_displayStart( gwork, 0, 0, 0 ) ;    /* 表示開始位置 */
  174.  EGB_displayStart( gwork, 1, 0, 0 ) ;    /* 仮想画面中の位置 */
  175.  
  176.  EGB_writePage( gwork, 0 ) ;             /* 書き込みページを0に */
  177.  EGB_displayStart( gwork, 2, 2, 2 ) ;    /* 表示範囲の倍率設定(2X2) */
  178.  EGB_displayStart( gwork, 3, 320,240 ) ; /* 表示範囲の設定 */
  179.  EGB_displayStart( gwork, 0, 0, 0 ) ;    /* 表示開始位置 */
  180.  EGB_displayStart( gwork, 1, 0, 0 ) ;    /* 仮想画面中の位置 */
  181.  
  182.  EGB_fontStyle(gwork,1);      /* 太文字 */
  183.  EGB_textZoom(gwork,0,8,16);  /* ANKの拡大率 */
  184.  EGB_textZoom(gwork,1,16,16); /* 漢字の拡大率 */
  185.  EGB_color(gwork,0,0x7fff);   /* 文字色→白 */
  186.  
  187.  
  188.  MODE=0; BALL=1; /* 初期値 */
  189.  
  190.  while(1) /* ゲームループ */
  191.   {
  192.    binit();       /* BGMの初期化 */
  193.  
  194.    while(1)
  195.     {
  196.      rc=demo(); g_cls();          /* デモ(ゲームモード,レベル選択) */
  197.      if (rc==0) {GAME=0; break;}; /* ゲーム開始 */
  198.      if (rc==1) select_mode();    /* ゲームモード,ボール選択画面 */
  199.      if (rc==2) {GAME=1; break;}; /* ゲーム終了 */
  200.     };
  201.    if (GAME==1) /* ゲーム終了 */
  202.     {
  203.      save_best(); /* ベストタイムのバイナリ形式save */
  204.      break;       /*ゲームループ脱出 */
  205.     };
  206.  
  207.    init();
  208.  
  209.    while(END==0) /* 1ステージループ */
  210.     {
  211.      move(); /* 仮想VRAM中の表示位置の移動 */
  212.      s=deg+54; if (s>71) s=s-72; /* 進角 */
  213.      roll3(XOF[s],YOF[s],VRAM+W_PAGE,kvram[0],bx>>SHIFT,by>>SHIFT);
  214.      g_put2(MYADD+W_PAGE,chr[10+BALL]); /* ボールの表示 */
  215.      page(W_PAGE>>10); W_PAGE=W_PAGE^0x20000; /* 改ページ */
  216.      timer(232,106,TIME); /* 経過時間の表示 */
  217.      bgm();
  218.      if ((INPB(0x04d0) & 0x03)==0) /* SELECTボタン押下 -> 強制終了 */
  219.       {END=1; TIME=15000;};
  220.     };
  221.  
  222.    fm_init();
  223.    while ((INPB(0x04d0) & 0x3f)!=0x3f); /* パッドを放すまで待つ */
  224.    top_time(); /* ベストタイム一覧表示 */
  225.   };
  226.  
  227.  screenterm(gwork); /* MS-DOSの画面モードに設定する。*/
  228.  
  229. };
  230.  
  231.  
  232. init()
  233.         /* 1ゲーム毎の初期化処理 */
  234. {
  235.  int i,j,k;
  236.  int x,y;
  237.  
  238.  W_PAGE=0; /* レイア1の書き込みページ(0=(0,0) 0x20000=(0,128)) */
  239.  VRAM=g_loc(0,4)+0x40000;  /* VRAMの先頭アドレス */
  240.  MYADD=VRAM+48*2-(DY+8)*0x400; /* ボールの画面上での描画アドレス */
  241.  deg=0;    /* 重力の方向 */
  242.  ax=ay=0;  /* 加速度 */
  243.  vx=vy=0;  /* 速度 */
  244.  
  245. switch(BALL)
  246.  {     /* 重力加速度(1/A),最高速の絶対値,跳ね返り係数(%) */
  247.   case 0:     A=6;             V=4;        BOUND=70; break; /* 軽い */
  248.   case 1:     A=8;             V=6;        BOUND=60; break; /* 普通 */
  249.   case 2:     A=10;            V=8;        BOUND=50; break; /* 重い */
  250.  };
  251.  
  252.  switch(MODE) /* ボールの座標(中心) */
  253.   {
  254.    case 0: bx=MAX_X/2*POINT; by=MAX_Y/2*POINT; break;
  255.    case 1: bx=(6*16+8)*POINT; by=(7*16+8)*POINT; break;
  256.    case 2: bx=(26*16+8)*POINT; by=(6*16+8)*POINT; break;
  257.    case 3: bx=(6*16+8)*POINT; by=(7*16)*POINT; break;
  258.    case 4: bx=(6*16+8)*POINT; by=(7*16)*POINT; break;
  259.    case 5: bx=((56-16)*16+8)*POINT; by=(7*16)*POINT; break;
  260.   };
  261.  
  262.  BF=0;  /* バウンドフラグ */
  263.  
  264.  TIME=0;    /* スタートしてからの経過時間 */
  265.  TIME_UP=0; /* 時間切れフラグ */
  266.  END=0;     /* ステージ終了フラグ */
  267.  if (MODE==0) NEXT=0; else NEXT=9; /* 次に通過するチェックポイントの番号 */
  268.  
  269.  if (MODE==0) /* マップの作成(ゲームモード0用) */
  270.    {
  271.     for (j=0;j<56;j++) {for (i=0;i<56;i++) MAP[j][i]=WALL+1+rnd(2);}; /* 空間*/
  272.     for (j=0;j<6;j++) {for (i=0;i<56;i++) MAP[j][i]=MAP[55-j][i]=10;}; /*枠*/
  273.     for (j=0;j<56;j++) {for (i=0;i<6;i++) MAP[j][i]=MAP[j][55-i]=10;}; /*枠*/
  274.     x=(bx>>SHIFT)/16; y=(by>>SHIFT)/16;
  275.     for (j=0;j<10;j++) /* チェックポイントキャラクタパターンの複写 */
  276.      {for (i=0;i<256;i++) tile[j][i]=goal_chr[j][i];};
  277.     for (i=0;i<10;i++) /* チェックポイントの作成 */
  278.      {
  279.       while(1) /* 空間にチェックポイント配置 */
  280.        {
  281.         j=rnd(43)+6; k=rnd(43)+6;
  282.         if ( (MAP[j][k]>=WALL) && (x!=k) && (y!=j) )
  283.          {MAP[j][k]=i; break;};
  284.         /*if (MAP[j][k]>=(WALL+2)) {MAP[j][k]=i; break;};*/
  285.        };
  286.      };
  287.     for (i=0;i<LEVEL;i++) /* 障害物の作成 */
  288.      {
  289.       while(1) /* 空間に障害物配置 */
  290.        {
  291.         j=rnd(43)+6; k=rnd(43)+6;
  292.         if ( (MAP[j][k]>=WALL) && (x!=k) && (y!=j) ) {MAP[j][k]=11; break;};
  293.        };
  294.      };
  295.    }
  296.   else /* マップの作成(ゲームモード1以降用) */
  297.    {
  298.     for (j=0;j<10;j++) /* ゴールキャラクタパターンの複写 */
  299.      {for (i=0;i<256;i++) tile[j][i]=goal_chr[j+10][i];};
  300.     for (j=0;j<56;j++) /* コースデータをマップに複写 */
  301.      {
  302.       for (i=0;i<56;i++)
  303.        {
  304.         k=CORSE[MODE-1][j][i];
  305.         if (k>WALL) MAP[j][i]=k+rnd(3); /* 空間なら適当なキャラクタに変換 */
  306.          else MAP[j][i]=k; /* 空間以外ならそのままのパターンを採用 */
  307.        };
  308.      };
  309.    };
  310.  
  311.  /* 仮想VRAMの初期画面作成 */
  312.  k=kvram;
  313.  for (j=0;j<56;j++)
  314.   {
  315.    for (i=0;i<56;i++) m_put(k+i*32,&(tile[MAP[j][i]]));
  316.    k=k+MAX_X*32;
  317.   };
  318.  
  319.  g_cls();
  320.  
  321.  back(); /* 背景画面の作成 */
  322.  
  323. };
  324.  
  325.  
  326. /* sqr(56^2+80^2)=97≒98 */
  327. #define LIM_MIN 98  /* X & Y の最小値 */
  328. #define LIM_MAX 797 /* X & Y の最大値(895-98) */
  329.  
  330.  
  331. move()
  332.           /* 仮想VRAM中の表示位置の移動 1994年5月25日 初版完成 */
  333. {
  334.  int p;
  335.  int wbx,wby;
  336.  int px,py,mx,my;
  337.  int rev_x,rev_y;
  338.  int aw;
  339.  int i;
  340.  int COUNER=POINT*5;
  341.  int map;
  342.  int x,y;
  343.  
  344. /* X=xcos+ysin Y=-xsin+ycos*/
  345.  
  346.  p=INPB(0x04d0);
  347.  
  348.  if ((p & 0x04)==0) {deg--; if (deg<0) deg=71;}; /* パッド左 */
  349.  if ((p & 0x08)==0) {deg++; if (deg>71) deg=0;}; /* パッド右 */
  350.  
  351.  ax=COS[deg]/A; ay=SIN[deg]/A; /* 加速度の計算 */
  352.  
  353.  VX_MAX=abs(COS[deg])*V; VX_MIN=-VX_MAX; /* X方向最高速,最低速の計算 */
  354.  aw=abs(ax); /* 最高速,最低速の変化に伴うX速度の補正*/
  355.  if (vx>VX_MAX) {vx=vx-aw; if (vx<VX_MAX) vx=VX_MAX;};
  356.  if (vx<VX_MIN) {vx=vx+aw; if (vx>VX_MIN) vx=VX_MIN;};
  357.  VY_MAX=abs(SIN[deg])*V; VY_MIN=-VY_MAX; /* Y方向最高速,最低速の計算 */
  358.  aw=abs(ay); /* 最高速,最低速の変化に伴うY速度の補正*/
  359.  if (vy>VY_MAX) {vy=vy-aw; if (vy<VY_MAX) vy=VY_MAX;};
  360.  if (vy<VY_MIN) {vy=vy+aw; if (vy>VY_MIN) vy=VY_MIN;};
  361.  
  362.  vx=vx+ax; if (vx>VX_MAX) vx=VX_MAX; if (vx<VX_MIN) vx=VX_MIN; /* X速度の計算*/
  363.  vy=vy+ay; if (vy>VY_MAX) vy=VY_MAX; if (vy<VY_MIN) vy=VY_MIN; /* Y速度の計算*/
  364.  
  365. /* 反射処理 */
  366.  for (i=0;i<4;i++)
  367.   {
  368.    switch(i) /* 四隅について障害物との接触判定をする */
  369.     {
  370.      case 0 : wbx=bx-COUNER; wby=by-COUNER; break;
  371.      case 1 : wbx=bx-COUNER; wby=by+COUNER; break;
  372.      case 2 : wbx=bx+COUNER; wby=by-COUNER; break;
  373.      case 3 : wbx=bx+COUNER; wby=by+COUNER; break;
  374.     };
  375.    px=((wbx+vx)>>SHIFT)/16; py=((wby+vy)>>SHIFT)/16; /*通常速度時の座標の計算*/
  376.    mx=((wbx-vx)>>SHIFT)/16; my=((wby-vy)>>SHIFT)/16; /*反転速度時の座標の計算*/
  377.    map=MAP[py][px]; /* 移動先のMAPコード */
  378.    if (map<=WALL) /* 移動先が障害物(チェックポイント)なら反射処理 */
  379.     {
  380.      rev_x=rev_y=0; /* 反射可能フラグ */
  381.      if (MAP[py][mx]>WALL) rev_x=1;  /* X方向に反転可能 */
  382.      if (MAP[my][px]>WALL) rev_y=1;  /* Y方向に反転可能 */
  383.     /* XY両方向反射可能 → 反転 & XY両方向速度減衰 */
  384.      if (rev_x==rev_y)
  385.       {vx=-vx*BOUND/100; vy=-vy*BOUND/100;
  386.        if ( (abs(vx)>POINT) && (abs(vy)>POINT) ) BF=1;}; /*バウンドフラグオン*/
  387.     /* X方向だけ反射可能 → X方向に反射 & X方向速度減衰 */
  388.      if ( (rev_x==1) && (rev_y==0) )
  389.       {vx=-vx*BOUND/100; if (abs(vx)>POINT) BF=1;}; /* バウンドフラグオン */
  390.     /* Y方向だけ反射可能 → Y方向に反射 & Y方向速度減衰 */
  391.      if ( (rev_x==0) && (rev_y==1) )
  392.       {vy=-vy*BOUND/100; if (abs(vy)>POINT) BF=1;}; /* バウンドフラグオン */
  393.      if (map<=NEXT) /* 移動先がチェックポイント */
  394.        {
  395.         /* ビュー上のチェックポイント消去 */
  396.         if (MODE==0) g_pset(g_loc(MX+v_next_x[NEXT],MY+v_next_y[NEXT]),B*31);
  397.         NEXT++; /* 次に通るチェックポイントの更新 */
  398.         if (NEXT==10) /* ゴールイン */
  399.          {
  400.           fm_init(); /* 音の停止 */
  401.           END=1; /* ステージ終了 */
  402.           x=32; y=64;
  403.           EGB_textZoom(gwork,1,32,32); /* 漢字の拡大率 */
  404.           EGB_color(gwork,0,0); EGB_putSjis(gwork,x+2,y+2,"CLEAR");
  405.           EGB_color(gwork,0,R*31); EGB_putSjis(gwork,x+1,y+1,"CLEAR");
  406.           EGB_color(gwork,0,(R+G)*31); EGB_putSjis(gwork,x,y,"CLEAR");
  407.           EGB_textZoom(gwork,1,16,16); /* 漢字の拡大率 */
  408.           while ((INPB(0x04d0) & 0x3f)!=0x3f); /* パッドを放すまで待つ */
  409.           x=60; y=208;
  410.           EGB_color(gwork,0,0); EGB_putSjis(gwork,x+2,y+2,"Push A Button");
  411.           EGB_color(gwork,0,0x7fff);EGB_putSjis(gwork,x+1,y+1,"Push A Button");
  412.           EGB_color(gwork,0,R*31);EGB_putSjis(gwork,x,y,"Push A Button");
  413.           while((INPB(0x04d0) & 0x10)==0x10); /* Aボタンを押すまで待つ */
  414.           return 0;
  415.          };
  416.         MAP[py][px]=WALL+1; /* チェックポイントを脱け殻に変える */
  417.         prtchr(kvram,px*16,py*16,tile[WALL+1+rnd(2)]);/*仮想VRAMも脱殻に変更*/
  418.         spoint[1]=sinit[1]; skunt[1]=0;    /* チェックポイント通過音発声 */
  419.        }
  420.       else
  421.        {
  422.         if (BF==1) /* 速度反転による1dot以上の移動あり(転がりでない) */
  423.          {
  424.           spoint[0]=sinit[0]; skunt[0]=0; /* バウンド音発声 */
  425.           BF=0; /* バウンドフラグクリア */
  426.          };
  427.        };
  428.      break; /* 反射したなら以降の障害物接触判定は中断 */
  429.     };
  430.   };
  431.  
  432.  /* ビュー上のボールの消去 */
  433.  g_pset(g_loc(MX+(bx>>SHIFT)/16,MY+(by>>SHIFT)/16),B*31);
  434.  
  435.  bx=bx+vx; by=by+vy; /* 新座標の計算 */
  436.  
  437.  view();  /* ビューの表示 */
  438.  
  439.  /* 時間経過処理 */
  440.  TIME++; /* 時間経過 */
  441.  if (TIME>15000) /* タイムアップ */
  442.   {
  443.    fm_init(); /* 音の停止 */
  444.    TIME--; /* 表示上の時間との誤差修正 */
  445.    TIME_UP=END=1;
  446.    x=8; y=64;
  447.    EGB_textZoom(gwork,1,32,32); /* 漢字の拡大率 */
  448.    EGB_color(gwork,0,0); EGB_putSjis(gwork,x+2,y+2,"Time Up");
  449.    EGB_color(gwork,0,R*31); EGB_putSjis(gwork,x+1,y+1,"Time Up");
  450.    EGB_color(gwork,0,(R+G)*31); EGB_putSjis(gwork,x,y,"Time Up");
  451.    EGB_textZoom(gwork,1,16,16); /* 漢字の拡大率 */
  452.    while ((INPB(0x04d0) & 0x3f)!=0x3f); /* パッドを放すまで待つ */
  453.    x=60; y=208;
  454.    EGB_color(gwork,0,0); EGB_putSjis(gwork,x+2,y+2,"Push A Button");
  455.    EGB_color(gwork,0,0x7fff);EGB_putSjis(gwork,x+1,y+1,"Push A Button");
  456.    EGB_color(gwork,0,R*31);EGB_putSjis(gwork,x,y,"Push A Button");
  457.    while((INPB(0x04d0) & 0x10)==0x10); /* Aボタンを押すまで待つ */
  458.   };
  459.  
  460. };
  461.  
  462.  
  463. view_init(x,y)
  464.                /* ビューの作成 */
  465.  int x,y;
  466. {
  467.  int i,j,m,color;
  468.  
  469.  MX=x; MY=y; /* ビューの表示位置 */
  470.  v_flush=0; /* 次に通るべきチェックポイントの点滅フラグ */
  471.  
  472.  for (j=0;j<DSP_Y/2;j++)
  473.   {
  474.    for (i=0;i<DSP_X/2;i++)
  475.     {
  476.      m=MAP[j][i];
  477.      if (m<10) {color=R*31; v_next_x[m]=i; v_next_y[m]=j;}
  478.       else {if (m==10) color=PANEL; else color=B*31;};
  479.      g_pset(g_loc(MX+i,MY+j),color);
  480.     };
  481.   };
  482.  
  483. };
  484.  
  485.  
  486. view()
  487.                /* ビューの表示 */
  488. {
  489.  int a;
  490.  
  491.  /* ボールの表示 */
  492.  g_pset(g_loc(MX+(bx>>SHIFT)/16,MY+(by>>SHIFT)/16),(R+G)*31);
  493.  
  494.  if (MODE==0) /* ゲームモード0の場合 */
  495.   { /* 次のチェックポイントの点滅 */
  496.    v_flush++; if (v_flush>20) v_flush=0;
  497.    a=g_loc(MX+v_next_x[NEXT],MY+v_next_y[NEXT]);
  498.    if (v_flush<10) g_pset(a,R*31); else g_pset(a,B*31);
  499.   };
  500.  
  501. };
  502.  
  503.  
  504. timer(x,y,time)
  505.               /* 経過時間変更 */
  506.  int x,y;
  507.  int time;
  508. {
  509.  int pos;
  510.  
  511. /* 経過時間の表示 */ 
  512.  pos=g_loc(x,y);
  513.  g_put(pos,&(chr[time/10000])); time=time%10000; pos=pos+32;
  514.  g_put(pos,&(chr[time/1000])); time=time%1000; pos=pos+32;
  515.  g_put(pos,&(chr[time/100])); time=time%100; pos=pos+32;
  516.  g_put(pos,&(chr[time/10])); time=time%10; pos=pos+32;
  517.  g_put(pos,&(chr[time]));
  518.  
  519. };
  520.  
  521.  
  522. top_time()
  523.             /* ベストタイム一覧表示 */
  524. {
  525.  int i;
  526.  short x,y;
  527.  char buf[3]={0x82,0x4f,0};
  528.  int no=10;
  529.  
  530.  page(0); /* 仮想レイア0を表示画面にする */
  531.  g_cls();
  532.  
  533.  while ((INPB(0x04d0) & 0x3f)!=0x3f); /* パッドを放すまで待つ */
  534.  
  535.  for (i=0;i<8;i++) /* スコアの順位算出 */
  536.   {if (TIME<=BEST_TIME[MODE][BALL][i]) {no=i; break;};};
  537.  if (no!=10) /* BEST8入賞 */
  538.   {
  539.    for (i=7;i>no;i--) /* BEST8の入れ換え */
  540.     BEST_TIME[MODE][BALL][i]=BEST_TIME[MODE][BALL][i-1];
  541.    BEST_TIME[MODE][BALL][no]=TIME;
  542.    x=120; y=56;
  543.    EGB_color(gwork,0,R*31);
  544.    EGB_putSjis(gwork,x+16*5+4+1,y+14+no*20+1,"←あなたの記録");
  545.    EGB_color(gwork,0,(R+G)*31);
  546.    EGB_putSjis(gwork,x+16*5+4,y+14+no*20,"←あなたの記録");
  547.   };
  548.  
  549.  x=120; y=20;
  550.  EGB_color(gwork,0,0x7fff);
  551.  EGB_putSjis(gwork,x,y,"コースNo");
  552.  buf[1]=0x4f+MODE; EGB_putSjis(gwork,x+16*4,y,buf);
  553.  
  554.  x=10; y=12;
  555.  g_put2(g_loc(x,y)+0x40000,chr[10+BALL]);
  556.  switch(BALL)
  557.   {
  558.    case 0: EGB_putSjis(gwork,x*2+40,y*2+24,"軽い"); break;
  559.    case 1: EGB_putSjis(gwork,x*2+40,y*2+24,"普通"); break;
  560.    case 2: EGB_putSjis(gwork,x*2+40,y*2+24,"重い"); break;
  561.   };
  562.  EGB_putSjis(gwork,x*2+40+32,y*2+24,"ボール使用でのトップタイム");
  563.  
  564.  x=120; y=56;
  565.  for (i=0;i<8;i++)
  566.   {
  567.    buf[1]=0x4f+i+1;
  568.    EGB_color(gwork,0,R*31);
  569.    EGB_putSjis(gwork,x-8-16*2+1,y+i*20+14+1,buf);
  570.    EGB_putSjis(gwork,x-8-16+1,y+i*20+14+1,"位");
  571.    EGB_color(gwork,0,0x7fff);
  572.    EGB_putSjis(gwork,x-8-16*2,y+i*20+14,buf);
  573.    EGB_putSjis(gwork,x-8-16,y+i*20+14,"位");
  574.    timer(x,y+i*20,BEST_TIME[MODE][BALL][i]);
  575.   };
  576.  
  577.  EGB_putSjis(gwork,96,232,"Aボタン → 了解");
  578.  
  579.  while((INPB(0x04d0) & 0x10)==0x10); /* Aボタンを押すまで待つ */
  580.  
  581. };
  582.  
  583.  
  584. back()
  585.         /* 背景画面作成 */
  586. {
  587.  int i,j,ad;
  588.  short x,y;
  589.  char buf[3]={0x82,0x4f,0};
  590.  
  591.  g_cls();
  592.  
  593. /* 背景画面塗りつぶし */
  594.  for (i=0;i<240;i++) box_full(0,i,320,i,PANEL); /* 画面塗りつぶし */
  595.  
  596. /* タイトル表示 */
  597.  x=228; y=20;
  598.  EGB_color(gwork,0,R*31); EGB_putSjis(gwork,x+1,y+1,"Great");
  599.  EGB_color(gwork,0,(R+G)*31);EGB_putSjis(gwork,x,y,"Great Fall");
  600.  y=y+18;
  601.  EGB_color(gwork,0,R*31); EGB_putSjis(gwork,x+1,y+1," Fall");
  602.  EGB_color(gwork,0,(R+G)*31);EGB_putSjis(gwork,x,y," Fall");
  603.  
  604. /* トップタイム表示 */
  605.  x=232; y=64;
  606.  EGB_color(gwork,0,R*31); EGB_putSjis(gwork,x+1,y+1,"Top Time");
  607.  EGB_color(gwork,0,0x7fff); EGB_putSjis(gwork,x,y,"Top Time");
  608.  timer(x,y+2,BEST_TIME[MODE][BALL][0]);
  609.  
  610. /* マイタイム表示 */
  611.  x=232; y=104;
  612.  EGB_color(gwork,0,R*31); EGB_putSjis(gwork,x+1,y+1,"Time");
  613.  EGB_color(gwork,0,0x7fff); EGB_putSjis(gwork,x,y,"Time");
  614.  timer(x,y+2,0);
  615.  
  616. /* ビュー表示 */
  617.  x=232; y=144;
  618.  EGB_color(gwork,0,R*31); EGB_putSjis(gwork,x+1,y+1,"マップ");
  619.  EGB_color(gwork,0,0x7fff); EGB_putSjis(gwork,x,y,"マップ");
  620.  view_init(x+8,y+2); /* ビューの作成 */
  621.  view();  /* ビューの表示 */
  622.  
  623. /* ゲームモード表示 */
  624.  x=232; y=232;
  625.  EGB_color(gwork,0,R*31); EGB_putSjis(gwork,x+1,y+1,"コースNo");
  626.  buf[1]=0x4f+MODE; EGB_putSjis(gwork,x+16*4+1,y+1,buf);
  627.  EGB_color(gwork,0,0x7fff); EGB_putSjis(gwork,x,y,"コースNo");
  628.  buf[1]=0x4f+MODE; EGB_putSjis(gwork,x+16*4,y,buf);
  629.  
  630.  /* Get Ready 表示 */
  631.  roll3(XOF[deg+54],YOF[deg+54],VRAM,kvram[0],bx>>SHIFT,by>>SHIFT);
  632.  g_put2(MYADD,chr[10+BALL]); /* ボールの表示 */
  633.  for (i=8;i<232;i++) box_full(0,i,DSP_X*2-1,i,0x8000); /* ゲーム画面枠消去 */
  634.  x=44; y=64;
  635.  EGB_color(gwork,0,0); EGB_putSjis(gwork,x+2,y+2,"Get Ready");
  636.  EGB_color(gwork,0,0x7fff); EGB_putSjis(gwork,x+1,y+1,"Get Ready");
  637.  EGB_color(gwork,0,R*31); EGB_putSjis(gwork,x,y,"Get Ready");
  638.  while ((INPB(0x04d0) & 0x3f)!=0x3f); /* パッドを放すまで待つ */
  639.  x=60; y=208;
  640.  EGB_color(gwork,0,0); EGB_putSjis(gwork,x+2,y+2,"Push A Button");
  641.  EGB_color(gwork,0,0x7fff);EGB_putSjis(gwork,x+1,y+1,"Push A Button");
  642.  EGB_color(gwork,0,R*31);EGB_putSjis(gwork,x,y,"Push A Button");
  643.  while((INPB(0x04d0) & 0x10)==0x10); /* Aボタンを押すまで待つ */
  644.  
  645.  for (i=8;i<232;i++) box_full(0,i,DSP_X*2-1,i,0x8000); /* ゲーム画面枠消去 */
  646.  
  647. };
  648.  
  649.  
  650. demo()
  651.        /* デモ 戻り値  0:ゲーム開始 1:ゲーム終了 */
  652. {
  653.  int p,w;
  654.  short x,y;
  655.  char buf[3]={0x82,0x4f,0};
  656.  int select=0;
  657.  
  658.  /* タイトル画面表示 */
  659.  page(0); /* 仮想レイア0を表示画面にする */
  660.  g_cls();
  661.  
  662.  while ((INPB(0x04d0) & 0x3f)!=0x3f); /* パッドを放すまで待つ */
  663.  x=0; y=40;
  664.  EGB_textZoom(gwork,1,32,32); /* 漢字の拡大率 */
  665.  EGB_color(gwork,0,R*31); EGB_putSjis(gwork,x+2,y+2,"Great Fall");
  666.  EGB_color(gwork,0,(R+G)*31);EGB_putSjis(gwork,x+1,y+1,"Great Fall");
  667.  EGB_color(gwork,0,0x7fff); EGB_putSjis(gwork,x,y,"Great Fall");
  668.  EGB_textZoom(gwork,1,16,16); /* 漢字の拡大率 */
  669.  
  670.  x=24; y=72;
  671.  EGB_color(gwork,0,0x7fff);
  672.  EGB_putSjis(gwork,x,y,"現在のコースNoは");
  673.  buf[1]=0x4f+MODE; EGB_putSjis(gwork,x+16*8,y,buf);
  674.  if (MODE==0)
  675.    EGB_putSjis(gwork,28,y+20,"10箇所のチェックポイントの通過時間を競う");
  676.   else
  677.    EGB_putSjis(gwork,28,y+20,"ゴールにたどり着くまでの時間を競う");
  678.  
  679.  x=12; y=52;
  680.  g_put2(g_loc(x,y)+0x40000,chr[10+BALL]);
  681.  switch(BALL)
  682.   {
  683.    case 0: EGB_putSjis(gwork,x*2+40,y*2+24,"現在は軽いボールを使用"); break;
  684.    case 1: EGB_putSjis(gwork,x*2+40,y*2+24,"現在は普通ボールを使用"); break;
  685.    case 2: EGB_putSjis(gwork,x*2+40,y*2+24,"現在は重いボールを使用"); break;
  686.   };
  687.  
  688.  x=120; y=160;
  689.  box_full(x,y-16,x+16*5,y,R*31);
  690.  EGB_color(gwork,0,0x7fff);
  691.  EGB_putSjis(gwork,x,y,"ゲーム開始");
  692.  EGB_putSjis(gwork,x+8,y+20,"設定変更");
  693.  EGB_putSjis(gwork,x,y+40,"ゲーム終了");
  694.  
  695.  EGB_putSjis(gwork,96,232,"Aボタン → 決定");
  696.  
  697.  while(1)
  698.   {
  699.    p=INPB(0x04d0);
  700.  
  701.    w=select;
  702.    if ((p & 0x01)==0) /* パッド上 */
  703.     {select--; if (select<0) select=0;};
  704.    if ((p & 0x02)==0) /* パッド下 */
  705.     {select++; if (select>2) select=2;};
  706.    if (w!=select)
  707.     {
  708.      x=120; y=160;
  709.      box_full(x,y+w*20-16,x+16*5,y+w*20,0);
  710.      box_full(x,y+select*20-16,x+16*5,y+select*20,R*31);
  711.      EGB_color(gwork,0,0x7fff);
  712.      EGB_putSjis(gwork,x,y,"ゲーム開始");
  713.      EGB_putSjis(gwork,x+8,y+20,"設定変更");
  714.      EGB_putSjis(gwork,x,y+40,"ゲーム終了");
  715.     };
  716.    if ((p & 0x10)==0) return(select); /* Aボタン */
  717.   };
  718.  
  719. };
  720.  
  721.  
  722. select_mode()
  723.               /* ゲームモード,ボール選択画面 */
  724. {
  725.  int p,i;
  726.  int sel_mode=0;
  727.  int end=0;
  728.  short w0,w1;
  729.  short x,y;
  730.  char buf[3]={0x82,0x4f,0};
  731.  
  732.  while ((INPB(0x04d0) & 0x3f)!=0x3f); /* パッドを放すまで待つ */
  733.  
  734.  /* 選択画面表示 */
  735.  page(0); /* 仮想レイア0を表示画面にする */
  736.  g_cls();
  737.  
  738.  /* 初期画面作成 */
  739.  EGB_color(gwork,0,0x7fff);
  740.  EGB_putSjis(gwork,40,20,"ボ-ルとコースを選択して下さい");
  741.  EGB_putSjis(gwork,96,232,"Aボタン → 決定");
  742.  /* ボールの表示 */
  743.  x=24; y=32;
  744.  for (i=0;i<3;i++) g_put2(g_loc(x+i*48,y)+0x40000,chr[10+i]);
  745.  EGB_color(gwork,0,R*31);
  746.  EGB_putSjis(gwork,x*2+72,y*2-8,"ボ-ル選択");
  747.  box(24,32,320-24,132,R*31);
  748.  for (i=0;i<3;i++)
  749.   {
  750.    if (i==BALL) EGB_color(gwork,0,R*31); else EGB_color(gwork,0,0x7fff);
  751.    switch(i)
  752.     {
  753.      case 0: EGB_putSjis(gwork,x*2,y*2+50,"軽い"); break;
  754.      case 1: EGB_putSjis(gwork,x*2+48*2,y*2+50,"普通"); break;
  755.      case 2: EGB_putSjis(gwork,x*2+48*4,y*2+50,"重い"); break;
  756.     };
  757.    };
  758.  y=60; x=96*BALL+44; box(x,y,x+38,y+56,R*31);
  759.  x=24; y=140;
  760.  EGB_color(gwork,0,0x7fff);
  761.  EGB_putSjis(gwork,x*2+72,y+16,"コース選択");
  762.  EGB_putSjis(gwork,x*2+72,y+40,"コースNo");
  763.  buf[1]=0x4f+MODE; EGB_putSjis(gwork,x*2+72+16*4,y+40,buf);
  764.  if (MODE==0)
  765.    EGB_putSjis(gwork,28,y+60,"10箇所のチェックポイントの通過時間を競う");
  766.   else
  767.    EGB_putSjis(gwork,25,y+60,"ゴールにたどり着くまでの時間を競う");
  768.  
  769.  while(end==0)
  770.   {
  771.    p=INPB(0x04d0);
  772.    switch(sel_mode)
  773.     {
  774.      case 0 : /* ボール選択 */
  775.       if ((p & 0x10)==0) {end=1; break;}; /* Aボタン */
  776.       if ((p & 0x02)==0) /* パッド下 */
  777.        {
  778.         EGB_color(gwork,0,0x7fff);
  779.         x=24; y=32; EGB_putSjis(gwork,x*2+72,y*2-8,"ボ-ル選択");
  780.         EGB_color(gwork,0,R*31);
  781.         x=24; y=140; EGB_putSjis(gwork,x*2+72,y+16,"コース選択");
  782.         box(24,32,320-24,132,0);
  783.         sel_mode=1;
  784.         box(24,132,320-24,232-20,R*31);
  785.        };
  786.       w0=BALL;
  787.       if ((p & 0x04)==0) {BALL--; if (BALL<0) BALL=2;}; /* パッド左 */
  788.       if ((p & 0x08)==0) {BALL++; if (BALL>2) BALL=0;}; /* パッド右 */
  789.       if (BALL!=w0)
  790.        {
  791.         x=24; y=32;
  792.         for (i=0;i<3;i++)
  793.          {
  794.           if (i==BALL) EGB_color(gwork,0,R*31); else EGB_color(gwork,0,0x7fff);
  795.           switch(i)
  796.            {
  797.             case 0: EGB_putSjis(gwork,x*2,y*2+50,"軽い"); break;
  798.             case 1: EGB_putSjis(gwork,x*2+48*2,y*2+50,"普通"); break;
  799.             case 2: EGB_putSjis(gwork,x*2+48*4,y*2+50,"重い"); break;
  800.            };
  801.          };
  802.         y=60; x=96*w0+44; box(x,y,x+38,y+56,0);
  803.         x=96*BALL+44; box(x,y,x+38,y+56,R*31);
  804.        };
  805.       break;
  806.      case 1 : /* ゲームモード選択 */
  807.       if ((p & 0x10)==0) {end=1; break;}; /* Aボタン */
  808.       if ((p & 0x01)==0) /* パッド上 */
  809.        {
  810.         EGB_color(gwork,0,R*31);
  811.         x=24; y=32; EGB_putSjis(gwork,x*2+72,y*2-8,"ボ-ル選択");
  812.         EGB_color(gwork,0,0x7fff);
  813.         x=24; y=140; EGB_putSjis(gwork,x*2+72,y+16,"コース選択");
  814.         box(24,132,320-24,232-20,0);
  815.         sel_mode=0;
  816.         box(24,32,320-24,132,R*31);
  817.        };
  818.       w1=MODE;
  819.       if ((p & 0x04)==0) {MODE--; if (MODE<0) MODE=5;}; /* パッド左 */
  820.       if ((p & 0x08)==0) {MODE++; if (MODE>5) MODE=0;}; /* パッド右 */
  821.       if (MODE!=w1)
  822.        {
  823.         x=24; y=140;
  824.         box_full(x*2+72+16*4,y+40-16,x*2+72+16*5,y+40,0);
  825.         EGB_color(gwork,0,0x7fff);
  826.         buf[1]=0x4f+MODE; EGB_putSjis(gwork,x*2+72+16*4,y+40,buf);
  827.         box_full(25,y+60-16,320-25,y+60,0);
  828.         EGB_color(gwork,0,0x7fff);
  829.         if (MODE==0)
  830.           EGB_putSjis(gwork,28,y+60,"10箇所のチェックポイントの通過時間を競う");
  831.          else
  832.           EGB_putSjis(gwork,25,y+60,"ゴールにたどり着くまでの時間を競う");
  833.        };
  834.       break;
  835.     };
  836.   };
  837.  g_cls();
  838.  
  839. };
  840.  
  841.  
  842. box(x0,y0,x1,y1,color)
  843.                          /* BOX描画 */
  844.  short x0,y0; /* 左上座標 */
  845.  short x1,y1; /* 右下座標 */
  846.  short color; /* 色 */
  847. {
  848.  short para[5]; /* EGB_Connect パラメータ */
  849.  
  850.  EGB_color(gwork,0,color);  /* 色の設定 */
  851.  
  852.  para[0]=2;
  853.  para[1]=x0; para[2]=y0; para[3]=x0; para[4]=y1;
  854.  EGB_unConnect(gwork,para);    /* 線分を描く */
  855.  para[1]=x0; para[2]=y1; para[3]=x1; para[4]=y1;
  856.  EGB_unConnect(gwork,para);    /* 線分を描く */
  857.  para[1]=x1; para[2]=y1; para[3]=x1; para[4]=y0;
  858.  EGB_unConnect(gwork,para);    /* 線分を描く */
  859.  para[1]=x1; para[2]=y0; para[3]=x0; para[4]=y0;
  860.  EGB_unConnect(gwork,para);    /* 線分を描く */
  861.  
  862.  
  863. };
  864.  
  865.  
  866. box_full(x0,y0,x1,y1,color)
  867.                          /* BOX描画(full) */
  868.  short x0,y0; /* 左上座標 */
  869.  short x1,y1; /* 右下座標 */
  870.  short color; /* 色 */
  871. {
  872.  short para[5]; /* EGB_Connect パラメータ */
  873.  short i;
  874.  
  875.  EGB_color(gwork,0,color);  /* 色の設定 */
  876.  
  877.  para[0]=2;
  878.  for (i=y0;i<=y1;i++)
  879.   {para[1]=x0; para[2]=para[4]=i; para[3]=x1; EGB_unConnect(gwork,para);};
  880.  
  881. };
  882.  
  883.  
  884.  
  885. page(hed)
  886.                  /* レイア1のハードスクロール */
  887. int hed;         /* レイア1の画面表示開始位置 */
  888. {
  889.  asm("      pushl %edx");
  890.  asm("      movl 12(%esp),%eax");    /* hed */
  891.  asm("      andl $0xff,%eax");
  892.  asm("      roll $8,%eax");
  893.  asm("      pushl %eax");            /* FA1 */
  894.  asm("      movw $0x440,%dx");
  895.  asm("      movb $21,%al");
  896.  asm("      outb %al,%dx");
  897.  asm("      popl %eax");             /* FA1 */
  898.  asm("      movw $0x442,%dx");
  899.  asm("      outw %ax,%dx");
  900.  asm("      popl %edx");
  901.  
  902. }; 
  903.  
  904.  
  905. init_tri()
  906.               /* 三角関数テーブルの作成 */
  907. {
  908.  int i,j;
  909.  double r; /* 回転角 */
  910.  
  911.  for (i=0;i<72;i++)
  912.   {
  913.    r=(360/72*i)*RAD; /* ラジアンへの変換 */
  914.    COS[i]=cos(r)*POINT; SIN[i]=sin(r)*POINT;
  915.   };
  916.  
  917. };
  918.  
  919.  
  920. init_tri3()
  921.  
  922. {
  923. /* X=xcos+ysin Y=-xsin+ycos*/
  924.  int i,j,o1,o2;
  925.  
  926.  for (i=0;i<72;i++)
  927.   {
  928.    for (j=0;j<DSP_X;j++)
  929.     {
  930.      o1=(DX+DSP_X)-j; o2=(DY+DSP_Y)-j;
  931.      XOF[i][j]=(((COS[i]*o1)>>12)+((SIN[i]*o1)>>12)*MAX_X)*2;
  932.      YOF[i][j]=(((-SIN[i]*o2)>>12)+((COS[i]*o2)>>12)*MAX_X)*2;
  933.     };
  934.   };
  935.  
  936. };
  937.  
  938.  
  939. roll3(xof,yof,vram,kvram,kx,ky)
  940. /*    44  48   52   56   60 64 */
  941.                                  /* 画面回転(高速版2) 1994年3月29日 */
  942.                                  /*              改良       3月30日 */
  943. /* X=xcos+ysin Y=-xsin+ycos*/
  944.  int *xof;      /* (cos×x(56:-56)-sin×y(56:-56)×MAX_X)×2 */
  945.  int *yof;      /* (-sin×x(56:-56)-cos×y(56:-56)×MAX_X)×2 */
  946.  int vram;     /* VRAM左上アドレス */
  947.  short *kvram; /* 仮想VRAM先頭アドレス -> 中心アドレス */
  948.  int kx,ky;    /* 仮想VRAM回転中心座標 -> X方向オフセット1,2*/
  949. {
  950.  asm("        pushal");
  951.  
  952.  asm("        pushl %es");
  953.  asm("        pushl $0x0104");
  954.  asm("        popl %es");
  955.  
  956.  asm("        cld");                /* ストリング方向フラグ=0 */
  957.  asm("        movl 64(%esp),%eax"); /* 中心 Y座標 */
  958.  asm("        movl $896,%ebx");     /* MAX_X */
  959.  asm("        mull %ebx");
  960.  asm("        addl 60(%esp),%eax"); /* 中心 X座標+中心 Y座標×MAX_X */
  961.  asm("        addl %eax,%eax");     /* ×2(仮想VRAM 中心座標のオフセット) */
  962.  asm("        addl %eax,56(%esp)"); /* +仮想VRAM先頭アドレス=>中心アドレス */
  963.  
  964.  asm("        movl 44(%esp),%ebp"); /* XOF先頭アドレス */
  965.  asm("        subl $4,%ebp"); /* XOF先頭アドレス-4 */
  966.  asm("        movl 48(%esp),%ebx"); /* YOF先頭アドレス */
  967.  asm("        subl $4,%ebx"); /* YOF先頭アドレス-4 */
  968.  asm("        movl $112,%ecx");     /* Y方向オフセット(1:DSP_Y) */
  969.  asm("lpY3:   movl 56(%esp),%edx"); /* 仮想VRAM中心アドレス */
  970.  asm("        addl %ss:(%ebx,%ecx,4),%edx"); /* kvram(中心)+YOF */
  971.  asm("        movl 52(%esp),%edi"); /* VRAM先頭アドレス */
  972.  asm("        pushl %ecx");
  973.  asm("        movl $112,%ecx");     /* X方向オフセット(1:DSP_X) */
  974.  
  975.  asm("lpX3:");
  976.  asm("        movl (%ebp,%ecx,4),%esi");  /* XOF  1*/
  977.  asm("        movw %ss:(%edx,%esi),%ax"); /* 仮想VRAM回転変換位置の色情報 */
  978.  asm("        stosw");                    /* 描画対象VRAMに転送しVRAM+2 */
  979.  asm("        decl %ecx");                /* X方向オフセット-1 */
  980.  
  981.  asm("        movl (%ebp,%ecx,4),%esi");  /* XOF  2*/
  982.  asm("        movw %ss:(%edx,%esi),%ax"); /* 仮想VRAM回転変換位置の色情報 */
  983.  asm("        stosw");                    /* 描画対象VRAMに転送しVRAM+2 */
  984.  asm("        decl %ecx");                /* X方向オフセット-1 */
  985.  
  986.  asm("        movl (%ebp,%ecx,4),%esi");  /* XOF  3*/
  987.  asm("        movw %ss:(%edx,%esi),%ax"); /* 仮想VRAM回転変換位置の色情報 */
  988.  asm("        stosw");                    /* 描画対象VRAMに転送しVRAM+2 */
  989.  asm("        decl %ecx");                /* X方向オフセット-1 */
  990.  
  991.  asm("        movl (%ebp,%ecx,4),%esi");  /* XOF  4*/
  992.  asm("        movw %ss:(%edx,%esi),%ax"); /* 仮想VRAM回転変換位置の色情報 */
  993.  asm("        stosw");                    /* 描画対象VRAMに転送しVRAM+2 */
  994.  asm("        decl %ecx");                /* X方向オフセット-1 */
  995.  
  996.  asm("        movl (%ebp,%ecx,4),%esi");  /* XOF  5*/
  997.  asm("        movw %ss:(%edx,%esi),%ax"); /* 仮想VRAM回転変換位置の色情報 */
  998.  asm("        stosw");                    /* 描画対象VRAMに転送しVRAM+2 */
  999.  asm("        decl %ecx");                /* X方向オフセット-1 */
  1000.  
  1001.  asm("        movl (%ebp,%ecx,4),%esi");  /* XOF  6*/
  1002.  asm("        movw %ss:(%edx,%esi),%ax"); /* 仮想VRAM回転変換位置の色情報 */
  1003.  asm("        stosw");                    /* 描画対象VRAMに転送しVRAM+2 */
  1004.  asm("        decl %ecx");                /* X方向オフセット-1 */
  1005.  
  1006.  asm("        movl (%ebp,%ecx,4),%esi");  /* XOF  7*/
  1007.  asm("        movw %ss:(%edx,%esi),%ax"); /* 仮想VRAM回転変換位置の色情報 */
  1008.  asm("        stosw");                    /* 描画対象VRAMに転送しVRAM+2 */
  1009.  asm("        decl %ecx");                /* X方向オフセット-1 */
  1010.  
  1011.  asm("        movl (%ebp,%ecx,4),%esi");  /* XOF  8*/
  1012.  asm("        movw %ss:(%edx,%esi),%ax"); /* 仮想VRAM回転変換位置の色情報 */
  1013.  asm("        stosw");                    /* 描画対象VRAMに転送しVRAM+2 */
  1014.  asm("        loopl lpX3");               /* X方向オフセット-1 */
  1015.  
  1016.  asm("        popl %ecx");
  1017.  asm("        addl $0x0400,52(%esp)"); /* VRAMアドレス+0x400 */
  1018.  asm("        loopl lpY3");        /* Y方向オフセット-1 */
  1019.  
  1020.  asm("        popl %es");
  1021.  
  1022.  asm("        popal");
  1023.  
  1024. };
  1025.  
  1026.  
  1027.  
  1028.  
  1029. prtchr(kvram,x,y,chr)
  1030.                                     /* パターン転送 1994年2月9日 */
  1031.  short *kvram; /* 仮想VRAM先頭アドレス */
  1032.  int x,y;      /* 転送座標左上 */
  1033.  short *chr;   /* キャラクタ先頭アドレス */
  1034. {
  1035.  asm("        pushal");
  1036.  
  1037.  asm("        pushl %es");
  1038.  asm("        pushl %ss");
  1039.  asm("        popl %es");
  1040.  asm("        pushl %ss");
  1041.  asm("        popl %ds");
  1042.  
  1043.  asm("        cld");                /* ストリング方向フラグ=0 */
  1044.  asm("        movl 52(%esp),%eax"); /* 転送先 Y座標 */
  1045.  asm("        movl $896,%ebx");
  1046.  asm("        mull %ebx");          /* ×MAX_X */
  1047.  asm("        addl 48(%esp),%eax"); /* 転送先 X座標 */
  1048.  asm("        addl %eax,%eax");     /* ×2 */
  1049.  asm("        addl 44(%esp),%eax"); /* 仮想VRAM描画開始アドレス */
  1050.  asm("        movl %eax,%edi");
  1051.  
  1052.  asm("        movl 56(%esp),%esi"); /* キャラクタ先頭アドレス */
  1053.  asm("        movl $16,%ebx");      /* Y方向ループカウンタ */
  1054.  asm("LY:     movl $16,%ecx");      /* X方向ループカウンタ */
  1055.  asm("LX:     lodsw"); /* キャラクタ -> ax & キャラクタアドレス+2 */
  1056.  asm("        orw %ax,%ax");
  1057.  asm("        jz skip");             /* キャラクタがNULL dotなら転送しない */
  1058.  asm("        stosw"); /* ax -> 仮想VRAM & 仮想VRAM描画アドレス+2 */
  1059.  asm("        loop LX");
  1060.  asm("        addl $1760,%edi");    /* 仮想VRAM描画アドレス+(MAX_X-16)×2 */
  1061.  asm("        decl %ebx");
  1062.  asm("        jnz LY");
  1063.  
  1064.  asm("        popl %es");
  1065.  
  1066.  asm("        popal");
  1067.  
  1068.  asm("        leave");
  1069.  asm("        ret");
  1070.  
  1071.  asm("skip:   addl $2,%edi");        /* 仮想VRAM描画アドレス+2 */
  1072.  asm("        loop LX");
  1073.  asm("        addl $1760,%edi");    /* 仮想VRAM描画アドレス+(MAX_X-16)×2 */
  1074.  asm("        decl %ebx");
  1075.  asm("        jnz LY");
  1076.  
  1077.  asm("        popl %es");
  1078.  
  1079.  asm("        popal");
  1080.  
  1081. };
  1082.  
  1083.  
  1084. int g_put2(a,c)
  1085.                    /* 16X16dot put */
  1086.  int a;            /* VRAMアドレス */
  1087.  short c[];        /* キャラクタデータ先頭アドレス */
  1088.  
  1089. {
  1090.  asm("    pushl %ebx");
  1091.  asm("    pushl %edx");
  1092.  asm("    pushl %esi");
  1093.  asm("    pushl %edi");                  /* スタック +16 */
  1094.  
  1095.  asm("    movl  24(%esp),%eax");         /* VRAM アドレス */
  1096.  asm("    movl  28(%esp),%ebx");         /* キャラクタデータ アドレス */
  1097.  
  1098.  asm("    pushl %ds");
  1099.  
  1100.  asm("    pushl $0x0104");               /* VRAM セレクタ */
  1101.  asm("    popl  %ds");
  1102.  
  1103.  asm("    movl  $0,%esi");               /* VRAM X方向オフセット */
  1104.  asm("    movl  $0,%edi");               /* キャラクタデータオフセット */
  1105.  asm("lva:movw  %ss:(%ebx,%edi,2),%edx");/* キャラクタデータ(2バイト)をedxにロード */
  1106.  asm("    orw  %edx,%edx");              /* ヌルドットは表示しない */
  1107.  asm("    jz  pn");
  1108.  asm("    movw  %edx,(%eax,%esi,2)");    /* edxをVRAMにストア */
  1109.  asm("pn: incl  %edi");
  1110.  asm("    incl  %esi");
  1111.  asm("    cmpl  $16,%esi");             /* 1行分のループ */
  1112.  asm("    jnz   lva");
  1113.  asm("    movl  $0,%esi");               /* VRAM X方向オフセットのクリア */
  1114.  asm("    addl  $0x400,%eax");           /* VRAMアドレスの更新 */
  1115.  asm("    cmpl  $256,%edi");             /* 16X16dot分のループ */
  1116.  asm("    jnz   lva");
  1117.  
  1118.  asm("    popl  %ds");
  1119.  
  1120.  asm("    popl  %edi");
  1121.  asm("    popl  %esi");
  1122.  asm("    popl  %edx");
  1123.  asm("    popl  %ebx");
  1124.  
  1125. };
  1126.  
  1127.  
  1128. m_put(a,chr)
  1129.              /* マップ作成用パターン転送 1994年6月5日 */
  1130.  short *a;   /* 転送先仮想VRAM先頭アドレス */
  1131.  short *chr; /* キャラクタ先頭アドレス */
  1132. {
  1133.  asm("        pushal");
  1134.  
  1135.  asm("        pushl %es");
  1136.  asm("        pushl %ss");
  1137.  asm("        popl %es");
  1138.  asm("        pushl %ss");
  1139.  asm("        popl %ds");
  1140.  
  1141.  asm("        cld");                /* ストリング方向フラグ=0 */
  1142.  asm("        movl 44(%esp),%edi"); /* 仮想VRAM描画開始アドレス */
  1143.  asm("        movl 48(%esp),%esi"); /* キャラクタ先頭アドレス */
  1144.  asm("        movl $16,%ebx");      /* Y方向ループカウンタ */
  1145.  asm("LM:     movl $16,%ecx");      /* X方向ループカウンタ */
  1146.  asm("        repw");
  1147.  asm("        movsw"); /* chr -> 仮想VRAM & chrアドレス+2,仮想VRAMアドレス+2 */
  1148.  asm("        addl $1760,%edi");    /* 仮想VRAM描画アドレス+(MAX_X-16)×2 */
  1149.  asm("        decl %ebx");
  1150.  asm("        jnz LM");
  1151.  
  1152.  asm("        popl %es");
  1153.  
  1154.  asm("        popal");
  1155.  
  1156. };
  1157.  
  1158.  
  1159. /* チャンネル 0 : バウンド音
  1160.               1 : チェックポイント通過音
  1161.               2 :
  1162.               3 :
  1163.               4 :
  1164.               5 :
  1165. */
  1166. #define T0  1              /* バウンド音のテンポ */
  1167.  
  1168. int sdata[]={                      /* サウンドデータ OCT,TONE,VOL,LONG */
  1169.                             /* 音階 0  1  2  3  4  5  6  7  8  9  10 11 12
  1170.                                     休 C  C# D  D# E  F  F# G  G# A  A# B */
  1171.  
  1172.              -1,            /* No0 バウンド音 */
  1173.              5,12, 0,T0,
  1174.              6,1 , 0,T0,
  1175.              6,2 , 4,T0,
  1176.              6,1 , 8,T0,
  1177.              6,2 ,12,T0,
  1178.              6,1 ,20,T0,
  1179.              6,2 ,28,T0,
  1180.              6,1 ,36,T0,
  1181.              0, 0,128,0,
  1182.  
  1183.              -1,            /* No1 チェックポイント通過音 */
  1184.              5,12, 0,T0,
  1185.              5,12, 0,T0,
  1186.              6,1 , 0,T0,
  1187.              6,2 , 1,T0,
  1188.              6,1 , 2,T0,
  1189.              6,2 , 3,T0,
  1190.              6,1 , 4,T0,
  1191.              6,2 , 5,T0,
  1192.              6,1 , 6,T0,
  1193.              6,2 , 7,T0,
  1194.              6,1 , 8,T0,
  1195.              6,2 , 9,T0,
  1196.              6,1 ,10,T0,
  1197.              6,2 ,12,T0,
  1198.              6,1 ,14,T0,
  1199.              6,2 ,16,T0,
  1200.              6,1 ,18,T0,
  1201.              6,2 ,20,T0,
  1202.              6,1 ,22,T0,
  1203.              6,2 ,24,T0,
  1204.              6,1 ,26,T0,
  1205.              6,2 ,28,T0,
  1206.              6,1 ,30,T0,
  1207.              0, 0,128,0,
  1208.  
  1209.              -1,
  1210.              -2
  1211.             };
  1212.  
  1213.  
  1214. binit()
  1215.               /* BGM処理の初期化 */
  1216. {
  1217.  int i,j;
  1218.  
  1219.  for (i=j=0;sdata[i]!=-2;i++)
  1220.   {
  1221.    if (sdata[i]==-1) {sinit[j]=i+1; j++;}; /* サウンドデータ先頭位置の算出 */
  1222.   };
  1223.  
  1224.  for (i=0;i<6;i++) spoint[i]=0; /* サウンドデータポインタの初期化 */
  1225.  
  1226.  fm_init();
  1227.  
  1228. };
  1229.  
  1230.  
  1231. bgm()
  1232.               /* BGM処理 */
  1233. {
  1234.  int ch,oct,tone,vol;
  1235.  
  1236.  for (ch=0;ch<6;ch++)
  1237.   {
  1238.    if (sdata[spoint[ch]]>-1)  /* 休止状態でない */
  1239.     {
  1240.      skunt[ch]--;
  1241.      if (skunt[ch]<0)         /* 変音時期 */
  1242.       {
  1243.        oct=sdata[spoint[ch]]; spoint[ch]++;
  1244.        tone=sdata[spoint[ch]]; spoint[ch]++;
  1245.        vol=sdata[spoint[ch]]; spoint[ch]++;
  1246.        skunt[ch]=sdata[spoint[ch]]; spoint[ch]++;
  1247.        fm_sound(ch,oct,tone,vol,feed[ch]);
  1248.       };
  1249.     };
  1250.   };
  1251.  
  1252. };
  1253.  
  1254.  
  1255. load_chr()
  1256.            /* キャラクタパターンデータのバイナリ形式load */
  1257. {
  1258.  int i,j,k;
  1259.  unsigned int h,l,end_f;
  1260.  int no;
  1261.  FILE *fp;
  1262.  
  1263.  fp=fopen(CHRFILE,"rb"); if (fp==NULL) return 0;
  1264.  
  1265.  end_f=0;
  1266.  
  1267.  for (no=0;((no<13)&&(end_f==0));no++)
  1268.   {
  1269.    for (i=0;((i<16)&&(end_f==0));i++)
  1270.     {
  1271.      for (j=0;((j<16)&&(end_f==0));j++)
  1272.       {
  1273.        h=getc(fp); l=getc(fp); chr[no][j+16*i]=h*0x100+l;
  1274.        if (feof(fp)!=0) end_f=1;
  1275.       };
  1276.     };
  1277.   };
  1278.  fclose(fp);
  1279.  
  1280.  return 1;
  1281.  
  1282. };
  1283.  
  1284.  
  1285. load_tile()
  1286.            /* タイルデータのバイナリ形式load */
  1287. {
  1288.  int i,j,k;
  1289.  unsigned int h,l,end_f;
  1290.  int no;
  1291.  FILE *fp;
  1292.  
  1293.  fp=fopen(TILEFILE,"rb"); if (fp==NULL) return 0;
  1294.  
  1295.  end_f=0;
  1296.  
  1297.  for (no=0;((no<96)&&(end_f==0));no++)
  1298.   {
  1299.    for (i=0;((i<16)&&(end_f==0));i++)
  1300.     {
  1301.      for (j=0;((j<16)&&(end_f==0));j++)
  1302.       {
  1303.        h=getc(fp); l=getc(fp); tile[no][j+16*i]=h*0x100+l;
  1304.        if (feof(fp)!=0) end_f=1;
  1305.       };
  1306.     };
  1307.   };
  1308.  fclose(fp);
  1309.  
  1310.  return 1;
  1311.  
  1312. };
  1313.  
  1314.  
  1315. load_best()
  1316.            /* ベストタイムのバイナリ形式load */
  1317. {
  1318.  int i,j,k;
  1319.  unsigned int h,l;
  1320.  FILE *fp;
  1321.  
  1322.  for (i=0;i<8;i++) /* ベストタイムのクリア */
  1323.   {
  1324.    for (j=0;j<6;j++)
  1325.     {for (k=0;k<3;k++) BEST_TIME[j][k][i]=7000+i*500;};
  1326.   };
  1327.  fp=fopen(BESTFILE,"rb"); if (fp==NULL) return 0;
  1328.  
  1329.  for (i=0;i<6;i++)
  1330.   {
  1331.    for (j=0;j<3;j++)
  1332.     {
  1333.      for (k=0;k<8;k++)
  1334.       {h=getc(fp); l=getc(fp); BEST_TIME[i][j][k]=h*0x100+l;};
  1335.     };
  1336.   };
  1337.  
  1338.  fclose(fp);
  1339.  
  1340. };
  1341.  
  1342.  
  1343. save_best()
  1344.            /* ベストタイムのバイナリ形式save */
  1345. {
  1346.  int i,j,k;
  1347.  unsigned char h,l;
  1348.  FILE *fp;
  1349.  
  1350.  fp=fopen(BESTFILE,"wb"); if (fp==NULL) return 0;
  1351.  
  1352.  for (i=0;i<6;i++)
  1353.   {
  1354.    for (j=0;j<3;j++)
  1355.     {
  1356.      for (k=0;k<8;k++)
  1357.       {
  1358.        h=BEST_TIME[i][j][k]/0x100; putc(h,fp);
  1359.        l=BEST_TIME[i][j][k]%0x100; putc(l,fp);
  1360.       };
  1361.     };
  1362.   };
  1363.  
  1364.  fclose(fp);
  1365.  
  1366. };
  1367.  
  1368.  
  1369. load_map()
  1370.            /* マップデータのバイナリ形式load */
  1371. {
  1372.  int i,j,k;
  1373.  FILE *fp;
  1374.  
  1375.  fp=fopen(MAPFILE,"rb"); if (fp==NULL) return 0;
  1376.  
  1377.  for (k=0;k<5;k++)
  1378.   {
  1379.    for (j=0;j<56;j++) {for (i=0;i<56;i++) CORSE[k][j][i]=getc(fp);};
  1380.   };
  1381.  
  1382.  fclose(fp);
  1383.  
  1384.  return 1;
  1385.  
  1386. };
  1387.  
  1388.  
  1389. load_goal()
  1390.            /* ゴールパターンデータのバイナリ形式load */
  1391. {
  1392.  int i,j,k;
  1393.  unsigned int h,l;
  1394.  int no;
  1395.  FILE *fp;
  1396.  
  1397.  fp=fopen(GOALFILE,"rb"); if (fp==NULL) return(0);
  1398.  
  1399.  for (no=0;no<20;no++)
  1400.   {
  1401.    for (i=0;i<16;i++)
  1402.     {
  1403.      for (j=0;j<16;j++)
  1404.       {
  1405.        h=getc(fp); l=getc(fp); goal_chr[no][j+16*i]=h*0x100+l;
  1406.       };
  1407.     };
  1408.   };
  1409.  
  1410.  fclose(fp);
  1411.  
  1412.  return 1;
  1413.  
  1414. };
  1415.